import React, { useEffect, useRef, useState } from "react";
import styled from "@emotion/styled";
import { FiLoader, FiAlertCircle } from "react-icons/fi";

// 样式组件
const ScrollContainer = styled.div<{ maxHeight?: string }>`
  position: relative;
  overflow-y: auto;
  overflow-x: hidden;
  ${({ maxHeight }) => maxHeight && `max-height: ${maxHeight};`}

  /* 自定义滚动条 */
  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-track {
    background: var(--bg-secondary);
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: var(--text-tertiary);
    border-radius: 3px;
    transition: background 0.2s ease;
  }

  &::-webkit-scrollbar-thumb:hover {
    background: var(--text-secondary);
  }
`;

const LoadingIndicator = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  color: var(--text-secondary);
  font-size: 0.9rem;
  gap: 0.5rem;

  .spinner {
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
`;

const ErrorMessage = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  padding: 2rem;
  color: var(--error-color);
  text-align: center;
  gap: 1rem;

  .error-text {
    font-size: 0.9rem;
  }

  .retry-button {
    padding: 0.5rem 1rem;
    background: var(--error-color);
    color: white;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.85rem;
    transition: background 0.2s ease;

    &:hover {
      background: #d32f2f;
    }
  }
`;

const EndMessage = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  color: var(--text-tertiary);
  font-size: 0.85rem;
  border-top: 1px solid var(--border-color);
  margin-top: 1rem;
`;

const EmptyState = styled.div`
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  padding: 3rem 2rem;
  color: var(--text-secondary);
  text-align: center;
  gap: 1rem;

  .empty-icon {
    font-size: 3rem;
    color: var(--text-tertiary);
  }

  .empty-title {
    font-size: 1.1rem;
    font-weight: 500;
    color: var(--text-primary);
  }

  .empty-description {
    font-size: 0.9rem;
    max-width: 300px;
    line-height: 1.5;
  }
`;

// 加载骨架屏组件
const SkeletonItem = styled.div`
  padding: 1rem;
  border-bottom: 1px solid var(--border-color);

  .skeleton-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
  }

  .skeleton-avatar {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: linear-gradient(
      90deg,
      var(--bg-secondary) 25%,
      var(--bg-tertiary) 50%,
      var(--bg-secondary) 75%
    );
    background-size: 200% 100%;
    animation: skeleton-loading 1.5s infinite;
  }

  .skeleton-info {
    flex: 1;
  }

  .skeleton-line {
    height: 0.75rem;
    background: linear-gradient(
      90deg,
      var(--bg-secondary) 25%,
      var(--bg-tertiary) 50%,
      var(--bg-secondary) 75%
    );
    background-size: 200% 100%;
    animation: skeleton-loading 1.5s infinite;
    border-radius: 4px;
    margin-bottom: 0.5rem;

    &.short {
      width: 60%;
    }
    &.medium {
      width: 80%;
    }
    &.long {
      width: 100%;
    }
  }

  .skeleton-content {
    .skeleton-line {
      height: 0.875rem;
      margin-bottom: 0.75rem;
    }
  }

  @keyframes skeleton-loading {
    0% {
      background-position: -200% 0;
    }
    100% {
      background-position: 200% 0;
    }
  }
`;

// 组件接口
export interface InfiniteScrollProps {
  children: React.ReactNode;
  hasMore: boolean;
  loading: boolean;
  error?: Error | null;
  onLoadMore: () => void;
  onRetry?: () => void;
  loadingComponent?: React.ReactNode;
  errorComponent?: React.ReactNode;
  endMessage?: React.ReactNode;
  emptyComponent?: React.ReactNode;
  threshold?: number; // 触发加载的距离阈值
  maxHeight?: string;
  scrollTopThreshold?: number;
  className?: string;
  itemCount?: number; // 当前已加载的项目数量
  skeletonCount?: number; // 骨架屏显示数量
  enableSkeleton?: boolean; // 是否启用骨架屏
}

// 默认组件
const DefaultLoadingComponent = () => (
  <LoadingIndicator>
    <FiLoader className="spinner" size={16} />
    <span>加载中...</span>
  </LoadingIndicator>
);

const DefaultErrorComponent: React.FC<{
  onRetry?: () => void;
  error?: Error;
}> = ({ onRetry, error }) => (
  <ErrorMessage>
    <FiAlertCircle size={24} />
    <div className="error-text">{error?.message || "加载失败，请重试"}</div>
    {onRetry && (
      <button className="retry-button" onClick={onRetry}>
        重试
      </button>
    )}
  </ErrorMessage>
);

const DefaultEndMessage = () => <EndMessage>— 没有更多内容了 —</EndMessage>;

const DefaultEmptyComponent = () => (
  <EmptyState>
    <div className="empty-icon">📝</div>
    <div className="empty-title">暂无内容</div>
    <div className="empty-description">
      这里还没有任何内容，快来创建第一条记录吧！
    </div>
  </EmptyState>
);

const DefaultSkeletonComponent: React.FC<{ count: number }> = ({ count }) => (
  <>
    {Array.from({ length: count }).map((_, index) => (
      <SkeletonItem key={index}>
        <div className="skeleton-header">
          <div className="skeleton-avatar" />
          <div className="skeleton-info">
            <div className="skeleton-line short" />
            <div className="skeleton-line medium" />
          </div>
        </div>
        <div className="skeleton-content">
          <div className="skeleton-line long" />
          <div className="skeleton-line medium" />
          <div className="skeleton-line short" />
        </div>
      </SkeletonItem>
    ))}
  </>
);

const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
  children,
  hasMore,
  loading,
  error,
  onLoadMore,
  onRetry,
  loadingComponent,
  errorComponent,
  endMessage,
  emptyComponent,
  threshold = 100,
  maxHeight,
  className,
  itemCount = 0,
  skeletonCount = 3,
  enableSkeleton = true,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const loadingRef = useRef<HTMLDivElement>(null);
  const sentinelRef = useRef<HTMLDivElement>(null); // 单独的哨兵元素 ref
  const isLoadingRef = useRef(false); // 用于防止重复触发的 ref
  const [isInitialLoad, setIsInitialLoad] = useState(true);

  // 同步 loading 状态到 ref，用于在 Intersection Observer 回调中检查（避免闭包问题）
  useEffect(() => {
    isLoadingRef.current = loading;
  }, [loading]);

  // 使用 Intersection Observer 检测是否需要加载更多
  useEffect(() => {
    // 使用哨兵元素来触发加载，而不是 loading 指示器
    const sentinel = sentinelRef.current;
    // 只在有更多数据且没有错误时才观察
    if (!sentinel || !hasMore || error) return;

    const observer = new IntersectionObserver(
      (entries) => {
        const target = entries[0];
        // 当哨兵元素进入视口时立即触发加载（使用 ref 检查 loading 状态，避免闭包问题）
        if (target.isIntersecting && !isLoadingRef.current) {
          onLoadMore();
        }
      },
      {
        root: containerRef.current,
        // 在底部设置提前触发区域，提前 threshold 像素触发加载
        rootMargin: `0px 0px ${threshold}px 0px`,
        // 设置为 0，只要有任何部分可见就触发
        threshold: 0,
      }
    );

    observer.observe(sentinel);

    return () => {
      observer.disconnect();
    };
  }, [hasMore, error, onLoadMore, threshold]);

  // 检测是否是初始加载 - 当 loading 从 true 变为 false 时，结束初始加载状态
  useEffect(() => {
    // 如果有数据，立即结束初始加载
    if (itemCount > 0) {
      setIsInitialLoad(false);
      return;
    }
    // 如果加载完成且没有数据，也结束初始加载状态
    if (!loading) {
      setIsInitialLoad(false);
    }
  }, [itemCount, loading]);

  // 渲染内容
  const renderContent = () => {
    // 空状态：加载完成、没有错误、没有数据
    // 注意：即使 isInitialLoad 还是 true，只要 loading 是 false 且 itemCount 是 0，就显示空状态
    if (!loading && !error && itemCount === 0) {
      return emptyComponent || <DefaultEmptyComponent />;
    }

    return (
      <>
        {children}

        {/* 哨兵元素 - 用于触发加载，必须始终存在（即使 loading 中） */}
        {hasMore && !error && (
          <div
            ref={sentinelRef}
            style={{
              height: "20px",
              minHeight: "20px",
              width: "100%",
              pointerEvents: "none",
            }}
          />
        )}

        {/* 加载指示器 */}
        {loading && (
          <div ref={loadingRef}>
            {isInitialLoad && enableSkeleton ? (
              <DefaultSkeletonComponent count={skeletonCount} />
            ) : (
              loadingComponent || <DefaultLoadingComponent />
            )}
          </div>
        )}

        {/* 错误状态 */}
        {error &&
          !loading &&
          (errorComponent || (
            <DefaultErrorComponent
              error={error}
              onRetry={onRetry || onLoadMore}
            />
          ))}

        {/* 结束消息 */}
        {!hasMore &&
          !loading &&
          !error &&
          itemCount > 0 &&
          (endMessage || <DefaultEndMessage />)}
      </>
    );
  };

  return (
    <>
      <ScrollContainer
        ref={containerRef}
        maxHeight={maxHeight}
        className={className}
      >
        {renderContent()}
      </ScrollContainer>
    </>
  );
};

export default InfiniteScroll;
